home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
LIBIMAGE
/
DRAW.C
next >
Wrap
C/C++ Source or Header
|
1999-09-11
|
29KB
|
1,195 lines
/*
* draw.c
*
* Practical Algorithms for Image Analysis
*
* Copyright (c) 1999 SOS Software
*/
#include "draw.h"
#include "mtables.c"
#define ERRORMEM(arg1) {fprintf (stderr,"%s: not enough memory -- sorry\n", arg1);exit (1);}
#define SIGN(a) ( ((a) == 0.0) ? 0 : ( ((a) < 0.0) ? -1 : 1 ) )
#define F_TO_INT(x) ( ((x)-(int)(x)<0.5) ? (int)(x) : (int)(x)+1 )
#define CS30 0.8660254
/*
* draw_line()
* DESCRIPTION:
* draw_line draws a line from point (x1,y1) to (x2,y2) using Bresenham's algorithm.
* ARGUMENTS:
* x1, y1, x2, y2(int) start and end points of line
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) pixel value to use for line
* RETURN VALUE:
* none
*/
void
draw_line (int x1, int y1, int x2, int y2, Image * imgIO, int value)
{
int x = x1;
int y = y1;
int D = 0;
int dx = x2 - x1;
int dy = y2 - y1;
int c;
int M;
int xinc = 1;
int yinc = 1;
if (dx < 0) {
xinc = -1;
dx = -dx;
}
if (dy < 0) {
yinc = -1;
dy = -dy;
}
if (dy < dx) {
c = 2 * dx;
M = 2 * dy;
while (x != x2) {
setpixel (x, y, imgIO, value);
x += xinc;
D += M;
if (D > dx) {
y += yinc;
D -= c;
}
}
}
else {
c = 2 * dy;
M = 2 * dx;
while (y != y2) {
setpixel (x, y, imgIO, value);
y += yinc;
D += M;
if (D > dy) {
x += xinc;
D -= c;
}
}
}
}
/*
* draw_circle()
* DESCRIPTION:
* draw_circle draws a circle specified by a center point and radius.
* ARGUMENTS:
* xC, yC(int) center point of circle
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) pixel value to use for circle
* RETURN VALUE:
* none
*/
void
draw_circle (int xC, int yC, int R, Image * imgIO, int value)
{
int x = 0;
int y = R;
int u = 1;
int v = 2 * R - 1;
int E = 0;
setpixel (xC, yC + R, imgIO, value);
setpixel (xC, yC - R, imgIO, value);
setpixel (xC + R, yC, imgIO, value);
setpixel (xC - R, yC, imgIO, value);
while (x < y) {
x++;
E += u;
u += 2;
if (v < 2 * E) {
y--;
E -= v;
v -= 2;
}
if (x <= y) {
setpixel (xC + x, yC + y, imgIO, value);
setpixel (xC - x, yC + y, imgIO, value);
setpixel (xC + x, yC - y, imgIO, value);
setpixel (xC - x, yC - y, imgIO, value);
if (x < y) {
setpixel (xC + y, yC + x, imgIO, value);
setpixel (xC - y, yC + x, imgIO, value);
setpixel (xC + y, yC - x, imgIO, value);
setpixel (xC - y, yC - x, imgIO, value);
}
}
}
}
/*
* draw_filled_circle()
* DESCRIPTION:
* draw_circle draws a circle specified by a center point and radius.
* fills the circle with value
* ARGUMENTS:
* xC, yC(int) center point of circle
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) pixel value to use for circle
* RETURN VALUE:
* none
*/
void
draw_filled_circle (int xC, int yC, int R, Image * imgIO, int value)
{
int x = 0;
int y = R;
int u = 1;
int v = 2 * R - 1;
int E = 0;
draw_line (xC, yC + R, xC, yC - R, imgIO, value);
draw_line (xC + R, yC, xC - R, yC, imgIO, value);
while (x < y) {
x++;
E += u;
u += 2;
if (v < 2 * E) {
y--;
E -= v;
v -= 2;
}
if (x <= y) {
draw_line (xC + x, yC + y, xC + x, yC - y, imgIO, value);
draw_line (xC - x, yC + y, xC - x, yC - y, imgIO, value);
if (x < y) {
draw_line (xC + y, yC + x, xC - y, yC + x, imgIO, value);
draw_line (xC + y, yC - x, xC - y, yC - x, imgIO, value);
}
}
}
}
/*
* NOTE: The functions
* gdImageCharUp
* gdImageCharUp
* gdImageString
* gdImageStringUp
* draw_ellipse
* gdImageFill
* gdImageFillToBorder
* are taken from the gd library and used with permission
* from T. Boutell
* * */
/*
* gdImageChar()
* DESCRIPTION:
* gdImageChar draws a character at the specified point using the specified font.
* ARGUMENTS:
* f(gdFontPtr) pointer to the font (see gd.h)
* x, y(int) point of origin for character
* c(int) character to draw
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) pixel value to use for character
* RETURN VALUE:
* none
*/
void
gdImageChar (gdFontPtr f, int x, int y, int c, Image * imgIO, int value)
{
int cx, cy;
int px, py;
int fline;
cx = 0;
cy = 0;
if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
return;
}
fline = (c - f->offset) * f->h * f->w;
for (py = y; (py < (y + f->h)); py++) {
for (px = x; (px < (x + f->w)); px++) {
if (f->data[fline + cy * f->w + cx]) {
setpixel (px, py, imgIO, value);
}
cx++;
}
cx = 0;
cy++;
}
}
/*
* gdImageCharUp()
* DESCRIPTION:
* gdImageCharUp draws a character at the specified point using the specified font
* rotated 90 degrees.
* ARGUMENTS:
* f(gdFontPtr) pointer to the font (see gd.h)
* x, y(int) point of origin for character
* c(int) character to draw
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) pixel value to use for character
* RETURN VALUE:
* none
*/
void
gdImageCharUp (gdFontPtr f, int x, int y, char c, Image * imgIO, int value)
{
int cx, cy;
int px, py;
int fline;
cx = 0;
cy = 0;
if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
return;
}
fline = (c - f->offset) * f->h * f->w;
for (py = y; (py > (y - f->w)); py--) {
for (px = x; (px < (x + f->h)); px++) {
if (f->data[fline + cy * f->w + cx]) {
setpixel (px, py, imgIO, value);
}
cy++;
}
cy = 0;
cx++;
}
}
/*
* gdImageString()
* DESCRIPTION:
* gdImageCharUp draws a string at the specified point using the specified font.
* ARGUMENTS:
* f(gdFontPtr) pointer to the font (see gd.h)
* x, y(int) point of origin for character
* c(char *) string to draw
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) pixel value to use for character
* RETURN VALUE:
* none
*/
void
gdImageString (gdFontPtr f, int x, int y, char *s, Image * imgIO, int value)
{
int i;
int l;
l = strlen (s);
for (i = 0; (i < l); i++) {
gdImageChar (f, x, y, s[i], imgIO, value);
x += f->w;
}
}
/*
* gdImageStringUp()
* DESCRIPTION:
* gdImageStringUp draws a string at the specified point using the specified font
* rotated 90 degrees.
* ARGUMENTS:
* f(gdFontPtr) pointer to the font (see gd.h)
* x, y(int) point of origin for character
* c(char *) string to draw
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) pixel value to use for character
* RETURN VALUE:
* none
*/
void
gdImageStringUp (gdFontPtr f, int x, int y, char *s, Image * imgIO, int value)
{
int i;
int l;
l = strlen (s);
for (i = 0; (i < l); i++) {
gdImageCharUp (f, x, y, s[i], imgIO, value);
y -= f->w;
}
}
/*
* draw_ellipse()
* DESCRIPTION:
* draw_ellipse draws an ellipse.
* ARGUMENTS:
* cx, cy(int) point of origin for ellipse
* w, h(int) width and height for ellipse
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) pixel value to use for character
* RETURN VALUE:
* none
*/
void
draw_ellipse (int cx, int cy, int w, int h, Image * imgIO, int value)
{
int i;
int lx = 0, ly = 0;
int w2, h2;
w2 = w / 2;
h2 = h / 2;
for (i = 0; (i <= 360); i++) {
int x, y;
x = ((long) cost[i % 360] * (long) w2 / costScale) + cx;
y = ((long) sint[i % 360] * (long) h2 / sintScale) + cy;
if (i) {
draw_line (lx, ly, x, y, imgIO, value);
}
lx = x;
ly = y;
}
}
/*
* gdImageFillToBorder()
* DESCRIPTION:
* gdImageFillToBorder floods a portion of the image with the specified value,
* beginning at the specified point and stopping at the specified border value.
* ARGUMENTS:
* x, y(int) point to start fill
* border(int) value of border at which to stop.
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for fill
* RETURN VALUE:
* # pixels filled
*/
long
gdImageFillToBorder (int x, int y, int border, Image * imgIO, int value)
{
int lastBorder;
/* Seek left */
int leftLimit, rightLimit;
int i;
long nfill = 0;
leftLimit = (-1);
if (border < 0) {
/* Refuse to fill to a non-solid border */
return (nfill);
}
for (i = x; (i >= 0); i--) {
//if (gdImageGetPixel(imgIO, i, y) == border) {
if (getpixel (i, y, imgIO) == border) {
break;
}
//gdImageSetPixel(im, i, y, color);
setpixel (i, y, imgIO, value);
nfill++;
leftLimit = i;
}
if (leftLimit == (-1)) {
return (nfill);
}
/* Seek right */
rightLimit = x;
for (i = (x + 1); (i < imgIO->width); i++) {
//if (gdImageGetPixel(im, i, y) == border) {
if (getpixel (i, y, imgIO) == border) {
break;
}
//gdImageSetPixel(im, i, y, color);
setpixel (i, y, imgIO, value);
nfill++;
rightLimit = i;
}
/* Look at lines above and below and start paints */
/* Above */
if (y > 0) {
lastBorder = 1;
for (i = leftLimit; (i <= rightLimit); i++) {
int c;
//c = gdImageGetPixel(im, i, y-1);
c = getpixel (i, y - 1, imgIO);
if (lastBorder) {
if ((c != border) && (c != value)) {
nfill += gdImageFillToBorder (i, y - 1,
border, imgIO, value);
lastBorder = 0;
}
}
else if ((c == border) || (c == value)) {
lastBorder = 1;
}
}
}
/* Below */
if (y < ((imgIO->height) - 1)) {
lastBorder = 1;
for (i = leftLimit; (i <= rightLimit); i++) {
int c;
//c = gdImageGetPixel(im, i, y+1);
c = getpixel (i, y + 1, imgIO);
if (lastBorder) {
if ((c != border) && (c != value)) {
nfill += gdImageFillToBorder (i, y + 1,
border, imgIO, value);
lastBorder = 0;
}
}
else if ((c == border) || (c == value)) {
lastBorder = 1;
}
}
}
return (nfill);
}
/*
* gdImageFill()
* DESCRIPTION:
* gdImageFill floods a portion of the image with the specified color,
* beginning at the specified point and flooding the surrounding region
* of the same color as the starting point.
* ARGUMENTS:
* x, y(int) point to start fill
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for fill
* RETURN VALUE:
* # pixels filled
*/
long
gdImageFill (int x, int y, Image * imgIO, int value)
{
int lastBorder;
int old;
int leftLimit, rightLimit;
int i;
int nfill = 0;
old = getpixel (x, y, imgIO);
//old = gdImageGetPixel(im, x, y);
if (old == value) {
/* Nothing to be done */
return (nfill);
}
/* Seek left */
leftLimit = (-1);
for (i = x; (i >= 0); i--) {
//if (gdImageGetPixel(im, i, y) != old) {
if (getpixel (i, y, imgIO) != old) {
break;
}
//gdImageSetPixel(im, i, y, color);
setpixel (i, y, imgIO, value);
nfill++;
leftLimit = i;
}
if (leftLimit == (-1)) {
return (nfill);
}
/* Seek right */
rightLimit = x;
for (i = (x + 1); (i < imgIO->width); i++) {
//if (gdImageGetPixel(im, i, y) != old) {
if (getpixel (i, y, imgIO) != old) {
break;
}
//gdImageSetPixel(im, i, y, color);
setpixel (i, y, imgIO, value);
nfill++;
rightLimit = i;
}
/* Look at lines above and below and start paints */
/* Above */
if (y > 0) {
lastBorder = 1;
for (i = leftLimit; (i <= rightLimit); i++) {
int c;
//c = gdImageGetPixel(im, i, y-1);
c = getpixel (i, y - 1, imgIO);
if (lastBorder) {
if (c == old) {
//gdImageFill(im, i, y-1, color);
nfill += gdImageFill (i, y - 1, imgIO, value);
lastBorder = 0;
}
}
else if (c != old) {
lastBorder = 1;
}
}
}
/* Below */
if (y < ((imgIO->height) - 1)) {
lastBorder = 1;
for (i = leftLimit; (i <= rightLimit); i++) {
int c;
//c = gdImageGetPixel(im, i, y+1);
c = getpixel (i, y + 1, imgIO);
if (lastBorder) {
if (c == old) {
//gdImageFill(im, i, y+1, color);
nfill += gdImageFill (i, y + 1, imgIO, value);
lastBorder = 0;
}
}
else if (c != old) {
lastBorder = 1;
}
}
}
return (nfill);
}
/*
* fill Voronoi diagram containing site (x, y)
*/
/*
* fill_Voronoi()
* DESCRIPTION:
* fill Voronoi diagram containing site (x, y)
* ARGUMENTS:
* x, y(double) coordinate of Voronoi site
* n(int) coordination number
* mode(int) fill mode
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* RETURN VALUE:
* none
*/
void
fill_Voronoi (double x, double y, int n, Image * imgIO, int mode)
{
int ix, iy;
int ind_5 = 3 * PIX_RANGE / 8;
int ind_7 = 5 * PIX_RANGE / 8;
int ind_4 = PIX_RANGE / 8;
int ind_8 = 7 * PIX_RANGE / 8;
ix = F_TO_INT (x);
iy = F_TO_INT (y);
ix += 3;
iy += 3;
if (mode == DISC_ONLY) {
if (n == 5)
gdImageFill (ix, iy, imgIO, ind_5);
if (n == 7)
gdImageFill (ix, iy, imgIO, ind_7);
if (n == 4)
gdImageFill (ix, iy, imgIO, ind_4);
if (n == 8)
gdImageFill (ix, iy, imgIO, ind_8);
}
}
/*
* draw_poly()
* DESCRIPTION:
* draw_poly draws a closed polygon with the specified value.
* ARGUMENTS:
* x, y(int *) list of (x,y) points for vertices
* n(int) number of (x,y) points
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for polygon border
* RETURN VALUE:
* none
*/
void
draw_poly (int *x, int *y, int n, Image * imgIO, int value)
{
int X;
int Y;
int i;
X = x[n - 1];
Y = y[n - 1];
for (i = 0; i < n; i++) {
draw_line (X, Y, x[i], y[i], imgIO, value);
X = x[i];
Y = y[i];
}
}
/*
* draw_poly_ovl()
* DESCRIPTION:
* draw_poly_ovl draws features over an existing polygon depending on polytype.
* ARGUMENTS:
* x, y(int *) list of (x,y) points for vertices
* n(int) number of (X,Y) points
* xc, yc(int) centroid of polygon
* av_dirn(double) average direction of polygon
* polytype(int) type of polygon
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for drawing
* RETURN VALUE:
* none
*/
void
draw_poly_ovl (int *x, int *y, int n,
int xc, int yc,
double av_dirn, int polytype,
Image * imgIO, int value)
{
int radius = 4;
int i;
if (polytype == APOLY) {
for (i = 0; i < n; i++)
draw_filled_circle (*(x + i), *(y + i), radius, imgIO, value);
}
else {
draw_poly (x, y, n, imgIO, value);
draw_square (xc, yc, radius, imgIO, value);
draw_normal (xc, yc, av_dirn, imgIO, value);
}
}
/*
* draw_polyfill()
* DESCRIPTION:
* draw_polyfill draws a closed polygon and fills it with the specified value.
* ARGUMENTS:
* x, y(int *) list of (x,y) points for vertices
* n(int) number of (x,y) points
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for polygon border and fill
* RETURN VALUE:
* number of pixels filled
*/
unsigned long
draw_polyfill (int *X, int *Y, int n, Image * imgIO, int value)
{
int x;
int y;
int i;
int ymin = 10000;
int ymax = 0;
int j;
int ny;
int i1;
int xP;
int yP;
int xQ;
int yQ;
int temp;
int dx;
int dy;
int m;
int dyQ;
int E;
int xleft;
int xright;
typedef struct element {
int xP;
int yQ;
int dx;
int dy;
int E;
struct element *next;
} element;
element **table, *p, *start, *end, *p0, *q;
unsigned long n_pixels;
n_pixels = 0;
x = X[n - 1];
y = Y[n - 1];
for (i = 0; i < n; i++) {
draw_line (x, y, X[i], Y[i], imgIO, value);
x = X[i];
y = Y[i];
if (y < ymin)
ymin = y;
if (y > ymax)
ymax = y;
}
ny = ymax - ymin + 1;
if ((table = (element **) calloc (ny, sizeof (element **))) == 0)
ERRORMEM ("draw_polyfill")
for (j = 0; j < ny; j++)
table[j] = NULL;
for (i = 0; i < n; i++) {
i1 = i + 1;
if (i1 == n)
i1 = 0;
xP = X[i];
yP = Y[i];
xQ = X[i1];
yQ = Y[i1];
if (yP == yQ)
continue;
if (yQ < yP) {
temp = xP;
xP = xQ;
xQ = temp;
temp = yP;
yP = yQ;
yQ = temp;
}
if ((p = (element *) calloc (1, sizeof (element))) == 0)
ERRORMEM ("draw_polyfill")
p->xP = xP;
p->dx = xQ - xP;
p->yQ = yQ;
p->dy = yQ - yP;
j = yP - ymin;
p->next = table[j];
table[j] = p;
}
if ((start = end = (element *) calloc (1, sizeof (element))) == 0)
ERRORMEM ("draw_polyfill")
for (j = 0; j < ny; j++) {
y = ymin + j;
p = start;
while (p != end) {
if (p->yQ == y) {
if ((q = p->next) == end)
end = p;
else
*p = *q;
free (q);
}
else {
if ((dx = p->dx) != 0) {
x = p->xP;
dy = p->dy;
E = p->E;
m = dx / dy;
dyQ = 2 * dy;
x += m;
E += 2 * dx - m * dyQ;
if (E > dy || E < -dy) {
if (dx > 0) {
x++;
E -= dyQ;
}
else {
x--;
E += dyQ;
}
}
p->xP = x;
p->E = E;
}
p = p->next;
}
}
p = table[j];
while (p != NULL) {
x = end->xP = p->xP;
yQ = p->yQ;
dx = p->dx;
dy = p->dy;
q = start;
while (q->xP < x ||
q->xP == x && q != end &&
(long) q->dx * dy < (long) dx * q->dy)
q = q->next;
p0 = p;
p = p->next;
if (q == end)
end = p0;
else
*p0 = *q;
q->xP = x;
q->yQ = yQ;
q->dx = dx;
q->dy = dy;
q->E = 0;
q->next = p0;
}
for (p = start; p != end; p = p->next) {
xleft = p->xP + 1;
p = p->next;
xright = p->xP - 1;
if (xleft <= xright) {
draw_horline (xleft, xright, y, imgIO, value);
/* calculate # pixels filled for area */
n_pixels = n_pixels + xright - xleft + 2;
}
}
}
p = start;
while (p != end) {
p0 = p;
p = p->next;
free (p0);
}
free (start);
free (table);
return (n_pixels);
}
/*
* draw_square()
* DESCRIPTION:
* draw_square draws a square with center at (x,y) and sides of size.
* ARGUMENTS:
* x, y(int) center point of square
* size(int) length of square sides
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for border
* RETURN VALUE:
* none
*/
void
draw_square (int x, int y, int size, Image * imgIO, int value)
{
draw_horline (x - size / 2, x + size / 2, y - size / 2, imgIO, value);
draw_horline (x - size / 2, x + size / 2, y + size / 2, imgIO, value);
draw_verline (x - size / 2, y - size / 2, y + size / 2, imgIO, value);
draw_verline (x + size / 2, y - size / 2, y + size / 2, imgIO, value);
}
/*
* draw_rect()
* DESCRIPTION:
* draw_rect draws a rectangle specified by an upper left point and a lower right point.
* ARGUMENTS:
* x1, y1(int) upper left point
* x2, y2(int) lower right point
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for border
* RETURN VALUE:
* none
*/
void
draw_rect (int x1, int y1, int x2, int y2, Image * imgIO, int value)
{
draw_horline (x1, x2, y1, imgIO, value);
draw_horline (x1, x2, y2, imgIO, value);
draw_verline (x1, y1, y2, imgIO, value);
draw_verline (x2, y1, y2, imgIO, value);
}
/*
* draw_cross()
* DESCRIPTION:
* draw_cross draws a cross with at the point (x,y).
* ARGUMENTS:
* x, y(int) center point of cross
* size(int) length in pixels for cross legs
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for border
* RETURN VALUE:
* none
*/
void
draw_cross (int x, int y, int size, Image * imgIO, int value)
{
draw_line (x - size / 2, y - size / 2, x + size / 2, y + size / 2, imgIO, value);
draw_line (x + size / 2, y - size / 2, x - size / 2, y + size / 2, imgIO, value);
}
/*
* draw_up_triang()
* DESCRIPTION:
* draw_up_triang draws an up triangle at the point (x,y).
* ARGUMENTS:
* x, y(int) center point of triangle
* offset(int) size of triangle in pixels
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for border
* RETURN VALUE:
* none
*/
void
draw_up_triang (int x, int y, int offset, Image * imgIO, int value)
{
int x_up, x_ll, x_lr, y_up, y_ll, y_lr;
x_up = x;
x_ll = x - (int) (offset * CS30);
x_lr = x + (int) (offset * CS30);
y_up = y - offset;
y_ll = y_lr = y + (offset / 2);
draw_line (x_up, y_up, x_ll, y_ll, imgIO, value);
draw_line (x_ll, y_ll, x_lr, y_lr, imgIO, value);
draw_line (x_lr, y_lr, x_up, y_up, imgIO, value);
}
/*
* draw_dn_triang()
* DESCRIPTION:
* draw_up_triang draws a down triangle at the point (x,y).
* ARGUMENTS:
* x, y(int) center point of triangle
* offset(int) size of triangle in pixels
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for border
* RETURN VALUE:
* none
*/
void
draw_dn_triang (int x, int y, int offset, Image * imgIO, int value)
{
int x_lw, x_ul, x_ur, y_lw, y_ul, y_ur;
x_lw = x;
x_ul = x - (int) (offset * CS30);
x_ur = x + (int) (offset * CS30);
y_lw = y + offset;
y_ul = y_ur = y - (offset / 2);
draw_line (x_lw, y_lw, x_ul, y_ul, imgIO, value);
draw_line (x_ul, y_ul, x_ur, y_ur, imgIO, value);
draw_line (x_ur, y_ur, x_lw, y_lw, imgIO, value);
}
/*
* draw_horline()
* DESCRIPTION:
* draw_horline draws a horizontal line.
* ARGUMENTS:
* xmin, xmax(int) min and max values for line
* y(int) y value for line
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for line
* RETURN VALUE:
* none
*/
void
draw_horline (int xmin, int xmax, int y, Image * imgIO, int value)
{
while (xmin <= xmax)
setpixel (xmin++, y, imgIO, value);
}
/*
* draw_verline()
* DESCRIPTION:
* draw_verline draws a vertical line.
* ARGUMENTS:
* x(int) x value for line
* ymin, ymax(int) ymin and ymax values for line
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for line
* RETURN VALUE:
* none
*/
void
draw_verline (int x, int ymin, int ymax, Image * imgIO, int value)
{
while (ymin <= ymax)
setpixel (x, ymin++, imgIO, value);
}
/*
* draw_normal()
* DESCRIPTION:
* draw_normal draws the direction normal to the average direction of segments in the
* present group list (given by their average slope, m) at the specified point;
* the slope of the normal is given by: mn = -1.0/m;
* ARGUMENTS:
* x, y(int) point to draw normal
* m(double) average slope
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) value to use for line
* RETURN VALUE:
* none
*/
void
draw_normal (int x, int y, double m, Image * imgIO, int value)
{
int offset = 10;
double foffset;
double fdelx, fdely;
int x_mn, x_pl, y_mn, y_pl;
int delx, dely;
double lolim = 0.01, uplim = 200.0;
if (fabs (m) < lolim) { /* horizontal segm */
x_mn = x_pl = x;
y_mn = y - offset;
y_pl = y + offset;
}
else if (fabs (m) > uplim) { /* vertical segm */
x_mn = x - offset;
x_pl = x + offset;
y_mn = y_pl = y;
}
else {
foffset = (double) offset;
fdely = foffset / sqrt (m * m + 1.0);
fdelx = fabs (m) * fdely;
if ((fdelx - (int) fdelx) < 0.5)
delx = (int) fdelx;
else
delx = (int) fdelx + 1;
if ((fdely - (int) fdely) < 0.5)
dely = (int) fdely;
else
dely = (int) fdely + 1;
y_mn = y - dely;
y_pl = y + dely;
if ((int) SIGN (m) > 0) { /* normal slope: SIGN(mn) < 0 */
x_mn = x + delx;
x_pl = x - delx;
}
else { /* normal slope: SIGN(mn) > 0 */
x_mn = x - delx;
x_pl = x + delx;
}
}
draw_line (x_mn, y_mn, x_pl, y_pl, imgIO, value);
}
/*
* setpixel()
* DESCRIPTION:
* setpixel sets the pixel at (x,y) with the supplied value
* ARGUMENTS:
* x, y(int) pixel point
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) pixel value to set
* RETURN VALUE:
* none
*/
void
setpixel (int x, int y, Image * imgIO, int value)
{
unsigned char **image; /* input/output image */
image = imgIO->img;
if (x < 0 || x >= imgIO->width || y < 0 || y >= imgIO->height) {
return;
}
else {
/*image is indexed by y first */
image[y][x] = (unsigned char) value;
}
}
/*
* getpixel()
* DESCRIPTION:
* getpixel gets the pixel at (x,y)
* ARGUMENTS:
* x, y(int) pixel point
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* RETURN VALUE:
* pixel value(unsigned char)
*/
unsigned char
getpixel (int x, int y, Image * imgIO)
{
unsigned char **image; /* input/output image */
image = imgIO->img;
if (x < 0 || x >= imgIO->width || y < 0 || y >= imgIO->height) {
return (0);
}
else {
/*image is indexed by y first */
return (image[y][x]);
}
}
/*
* getrow()
* DESCRIPTION:
* getrow gets the row of pixels
* ARGUMENTS:
* row_p(unsigned char *) pointer to row buffer
* row(int) which row to get
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* RETURN VALUE:
* none
*/
void
getrow (unsigned char *row_p, int row, Image * imgIO)
{
unsigned char **image; /* input/output image */
int ix;
image = imgIO->img;
for (ix = 0; ix < imgIO->width; ix++, row_p++) {
*row_p = image[row][ix];
}
}
/*
* draw_border()
* DESCRIPTION:
* draw_border sets a border defined by the
* upper left corner (jmin, imin) and
* lower right corner (jmax, imax) with value
* ARGUMENTS:
* (jmin, imin), (jmax, imax) bounding box
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value(int) pixel value to set
* RETURN VALUE:
* none
*/
void
draw_border (int jmin, int imin, int jmax, int imax, Image * imgIO, int value)
{
int ibmin, jbmin, ibmax, jbmax;
int ir, jc;
ibmin = 0;
ibmax = imgIO->height;
jbmin = 0;
jbmax = imgIO->width;
if (jmin < 0)
jmin = 0;
if (imin < 0)
imin = 0;
if (jmax >= imgIO->width)
jmax = imgIO->width;
if (imax >= imgIO->height)
imax = imgIO->height;
/* horizontal lines */
for (ir = ibmin; ir < imin; ir++)
draw_line (jbmin, ir, jbmax, ir, imgIO, value);
for (ir = imax + 1; ir < ibmax; ir++)
draw_line (jbmin, ir, jbmax, ir, imgIO, value);
/* vertical lines */
for (jc = jbmin; jc < jmin; jc++)
draw_line (jc, ibmin, jc, ibmax, imgIO, value);
for (jc = jmax + 1; jc < jbmax; jc++)
draw_line (jc, ibmin, jc, ibmax, imgIO, value);
}
/*
* zero_border()
* DESCRIPTION:
* zero_border sets a n-pixel wide border around the image to zero
* ARGUMENTS:
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* npix border width in pixels
* RETURN VALUE:
* none
*/
void
zero_border (Image * imgIO, int npix)
{
int i;
if (npix <= 0)
npix = 1;
for (i = 0; i < npix; i++) {
draw_line (i, i, imgIO->width - (1 + i), i, imgIO, BLACK);
draw_line (i, imgIO->height - (1 + i), imgIO->width - (1 + i), imgIO->height - (1 + i), imgIO, BLACK);
draw_line (i, i, i, imgIO->height - (1 + i), imgIO, BLACK);
draw_line (imgIO->width - (1 + i), i, imgIO->width - (1 + i), imgIO->height - (1 + i), imgIO, BLACK);
}
}
/*
* reset_image()
* DESCRIPTION:
* reset_image sets all the pixels in the entire image to value
* ARGUMENTS:
* imgIO(Image *) pointer to Image struct (see tiffimage.h)
* value grayscale value to use (0-255)
* RETURN VALUE:
* none
*/
void
reset_image (Image * imgIO, int value)
{
int ix;
int iy;
for (ix = 0; ix < imgIO->width; ix++)
for (iy = 0; iy < imgIO->height; iy++)
setpixel (ix, iy, imgIO, value);
}